結果我真的兩篇就快講完了(驚恐)。
既然是說要講切版的話,還是多少交代一些比較基礎的東西好了。
之前我們提及了多數 CSS 框架的設計,絕大部分都是 row
的主要軸流向。原因也相對單純,基本上你不太會擁有一個「無限寬度」的裝置,所以在目前主流裝置下,我們的寬度都會存在一個極大值,這個極大值基本上就會是整個 Flex 容器的主要軸尺寸。
所以,我們以雙欄結構來看,最單純的設定就會像是這樣,
.flex-container {
display: flex;
flex-flow: row wrap;
align-items: flex-start;
justify-content: flex-start;
}
接著,由於我們需要「雙欄」的設計,所以我們的元件定義就是,
.flex-item {
// 通用設定放這邊
margin: 0 10px;
}
.flex-aside {
// 側邊區塊,我們預設把他放在左邊
flex: 1 0 20%;
max-width: calc(20% - 20px);
}
.flex-main {
// 主要內容區塊,我們把他放在右邊
flex: 1 0 80%;
max-width: calc(80% - 10px);
// 取消左邊留白,讓我們的間隔看起來相同
margin-left: 0;
}
最終我們會獲得這樣的結果,
可是你不是說不要用
margin
來定義間隔(gap)嗎?
是的,我們在這邊也可以使用 padding
來製作我們間隔,但是,當你的 Flex 容器或是元件有使用背景設定時(background
),你還是得使用 margin
來當作間隔會比較適當。因為 background
會包含 padding
的留白部分,所以對於 Flex 元件來說,使用 margin
會比較適當。
當然,如果你使用背景的區塊是在 Flex 元件內的話,那麼使用 margin
或 padding
的差異就不大。另外,有些狀況使用 margin
是必須特別留意的,
stretch
的時候。margin
有需要使用 auto
的時候。對於 Flex 元件來說,margin
的關鍵字 auto
有一個特殊的效果,就是 自動補白 的特性。舉例來說,我們剛剛的主要欄位如果這樣設定,
.flex-main {
margin-left: auto;
}
那麼他就會將 剩餘空間 往左邊補白。請留意,這裡的剩餘空間是指容器本身的剩餘空間。由於我們使用了計算過後的 max-width
會將整個 Flex 容器填滿。在沒有填滿,且沒有設定 flex-grow: 1
的情況下,這個自動補白才會生效。
自動補白看起來好像很好用,不過,margin
會與部分樣式有權重問題,
margin
與 justify-content
, align-items
會產生疊加效應。auto
關鍵字會覆蓋部分 justify-content
與 align-items
的設定。margin
使用數值在一定條件(大於剩餘空間)下,會覆蓋 justify-content
與 align-items
的設定。只要是跟 剩餘空間 有關的部分都會受到影響。
請留意,無論是疊加還是干涉樣式設定,其本身的樣式還是有效的,以上述的例子來說,
.flex-main {
align-self: center;
margin-top: auto;
}
雖然最終呈現的狀態並非 align-self: center
的結果,但其自身還是受到 align-self: center
的樣式所規範。而左邊的 align-self: stretch;
也是一樣的道理。
另外,也會影響這個結果的則是 flex-grow
與 flex-shrink
這兩個樣式設定。我們先前有提到 flex-grow
是做一個 填充 的動作,所以,當你在沒有指定 Flex 元件的 軸方向 尺寸時,他會將軸方向作填滿動作。
換句話說,這個填滿跟 margin
的樣式權重,由大到小排列會是這樣,
margin
數值尺寸,例如 margin-left: 200px
flex-grow
flex-basis
|| width
|| max-width
|| height
|| max-height
margin
的關鍵字 auto
而如果是 flex-shrink
的話,就比較特殊了,由於他是 壓縮,所以在我們使用 margin
的情況下,並不會 觸發 壓縮這件事情,只有當 Flex 容器空間不足夠時才會觸發,且他也同樣會干擾壓縮的情況。
margin
數值尺寸,例如 margin-left: 200px
flex-shrink
flex-basis
|| width
|| min-width
|| height
|| min-height
margin
的關鍵字 auto
其順序上跟 flex-grow
雷同,但他的先決條件是 Flex 容器空間不足 的情況下才會發生。
基本上應用的方式與一般 Flex 容器沒有差異,就是單純的把 Flex 元件再次指定為 Flex 容器,在使用上沒有太大的區別。不過你得留意的是,原有區塊元件的父子元件同方向 margin
合併問題在巢狀結構中並不會發生。
也就是說,Flex 元件與容器會獨立擁有各自的 margin
,若 Box 元件沒有設定 overflow
的情況下,
.box-module-parent {
margin-top: 30px;
}
.box-module-child {
margin-top: 10px;
}
上述兩者因為同方向 margin
的關係,會產生合併(collapse),
而這件事情在 Flex 容器中不會發生,
.flex-module-parent {
margin-top: 30px;
}
.flex-module-child {
margin-top: 10px;
}
當然,你在一般 Flex 容器遇到的 margin
狀況,在這種情況下也免不了。所以,基本上多層次的運用 Flexbox 也不會有太多的意外,該寫的意外我應該都寫的八九成了。
Flexbox 終究還是拿來畫出框架的。
其實總的來說,這跟你用許多 CSS 框架的方式是雷同的,若是以 Bootstrap 為例子,其實就類似於,
<div class="conatiner">
<div class="row">
<div class="col-4">
</div>
<div class="col-8">
<div class="row">
<div class="col-6">
</div>
<div class="col-6">
</div>
</div>
</div>
</div>
</div>
這就端看你要怎麼去規劃你的框架該長成什麼樣子,只是在不使用 CSS 框架的情況下,你的 HTML 可以稍微簡潔一點點。當然,那種寫到爛掉的也不是沒有。
其實比較讓人覺得有趣的,大概就是置中對齊這件事情。
當然講到置中對齊,就得呼叫一下 Amos CSS垂直置中技巧,我只會23個,你會幾個
我只會一種,就是 align-items: center;
這樣。
說到對齊,就得提到 CSS 關於對齊的模組 CSS Box Alignment Module Level 3,但這邊不會提到太多,我們就單純的拿 Flexbox 可以使用的部分出來聊聊。
樣式 | 應用範圍 | 適用狀態 |
---|---|---|
justify-content |
Flex 容器 | 主要軸方向 |
align-content |
Flex 容器 | 交叉軸方向,多行狀態 |
align-items |
Flex 容器 | 主要軸方向 |
align-self |
Flex 元件 | 多行狀態 |
請注意有兩個樣式是必須要有 多行狀態 才會有效果。當然,說到對齊就必須得提到先前說過的 flex-grow
與 flex-shrink
這兩個樣式設定。在我們沒有特別指定主要軸、交叉軸尺寸,或是特別指定 Flex 元件尺寸的情況下,這兩個設定在某些情況下會讓你產生 客戶說沒對齊 的情況。
什麼叫做 客戶說沒對齊?
邏輯上來說,這是對齊的,但如果需要「根據底邊置中對齊」的時候,他就不符合預期結果。當然,請不要傳這一篇去給客戶看謝謝。 身為一個專業的前端工程師,這樣的問題也不是沒有解法。
你就把兩個元件鎖定相同高度就好(卍解)。
我在 Flexbox 最後面會解釋關於 Flex 的一些演算方式,這邊就暫不贅述。這樣的問題其實很常發生,當你的 Flex 容器允許斷行,在產生多行的情況下,由於整個容器的交叉軸尺寸是未知的(也就是隨內容動態增長),所以元件尺寸就會因為鄰近元件的關係而造成對齊點的問題。
以往我們使用區塊元件,利用 float: left;
大多會有這種狀況,
雖然 Flex 容器沒有 靠左對齊 的特性,但,
雖然沒有了奇怪的對齊點,但這就是所謂的有一好沒兩好。這一點在 Grid Layout Module 裡面會更明顯。所以,為了解決這種奇怪的補白問題,在一些必要情況下,請賦予你的 Flex 元件一個交叉軸尺寸,用以確保你在 flex-wrap: wrap;
的情況下會是比較好的呈現結果。
以下我直接用圖片來解釋各種 對齊,
附帶一題,最後的 space-evenly
是屬於對齊模組草稿階段,但瀏覽器支援度也是不錯。在 Caniuse 裡面有 95% 以上的支持度。
另外一個就是交叉軸的對齊(stretch
不算但我還是列出來),
基本會遇到的狀況在這邊大概可以涵蓋個七八成,所以這個時候你再回頭去看看那些知名 CSS 框架,應該就可以理解人家為什麼要這樣做。
下一次會提及一些關於 Media Query 的事情來聊聊 Flexbox 的使用情境。
目錄與小節:
[CSS] Flex/Grid Layout Modules, part 1
部落格同步放送:
[CSS] Flex/Grid Layout Modules, part 3